﻿using SuperX.Common;
using SuperX.Common.BasicService;
using SuperX.Common.Helper;
using SuperX.Common.Log;
using SuperX.Common.PlugIn;
using SuperX.DataService;
using SuperX.Helper;
using SuperX.Helper.PageBreak;
using SuperX.DeviceService.Model;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SuperX.DeviceService.Template
{
    internal class TemplateManager
    {
        private DeviceConfig DConfig { get; }
        public TemplateConfig TConfig { get; }

        private IProject _project { get; }

        private readonly DeviceServer _server;

        public TemplateManager(DeviceConfig config, DeviceServer server)
        {
            DConfig = config;
            _server = server;
            TConfig = DConfig.TemplateConfig;
            _project = BasicServiceManager.GetProjService().Project;
        }

        public bool CreateTemplate(DriverConfig driver, out string msg)
        {
            msg = string.Empty;
            var result = false;
            try
            {
                var templateDriver = driver.DeepCopy<TemplateDriverConfig>();
                templateDriver.TemplateId = GenerateUid.GenerateSnowFlake().ToString();
                TConfig.TemplateItem.Add(templateDriver);
                result = true;
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                Logger.ErrorException(ex);
            }
            return result;
        }

        internal string AddDriverByTemplate(int quantity, DriverConfig templateDriver, string nodeKey, bool isSync)
        {
            try
            {
                var regInfos = _server.DataManager.CheckReg();
                if (regInfos != null)
                {
                    var driverRegInfo = regInfos.RegBase.DriverRegInfo.Where(d => d.DriverFullName == templateDriver.ClassFullName).FirstOrDefault();
                    if (driverRegInfo != null)
                    {
                        var CurrentDriverNum = _server.DataManager.Config.DriverGroups.Values.Where(d => d.ClassFullName == templateDriver.ClassFullName && d.Enabled).ToList().Count;
                        if ((CurrentDriverNum + quantity) > driverRegInfo.RegOfNumber)
                        {
                            return "添加数量超出授权上限！";
                        }
                    }
                }

                var driverNames = GetDriverNames(templateDriver, quantity);
                foreach (var driverName in driverNames)
                {
                    var driver = templateDriver.DeepCopy<DriverConfig>();
                    driver.Name = driverName;
                    driver.NodeKey = nodeKey;
                    driver.TemplateSync = isSync;
                    DConfig.DriverGroups.Add(driver);
                }
                return "";
            }
            catch (Exception ex)
            {
                Logger.ErrorException(ex);
            }
            return "添加失败！";
        }

        public List<string> GetDriverNames(DriverConfig templateDriver, int quantity)
        {
            var result = new List<string>();
            var i = 0;

            while (result.Count < quantity)
            {
                i++;
                var name = templateDriver.Name + i.ToString();
                if (DConfig.DriverGroups.Values.FirstOrDefault(a => a.Name == name) == null) result.Add(name);
            }
            return result;
        }

        internal List<TemplateDriverConfig> GetTemplateCollection(List<BaseTreeNode> baseTreeNodes)
        {
            foreach (var item in TConfig.TemplateItem.Values)
            {
                var ids = JsonHelper.JsonDeserialize<List<string>>(item.PreDriverName);
                if (ids == null || ids.Count < 3) continue;
                var TreeNode = baseTreeNodes.Where(b => b.Id == ids[0]).FirstOrDefault();
                if (TreeNode == null) continue;
                var groupNode = GetNodeById(TreeNode, ids[1]);
                var manufac = GetNodeById(groupNode, ids[2]);
                item.DriverType = $"{TreeNode.Name} / {groupNode.Name} / {manufac.Name}";
            }
            return TConfig.TemplateItem.Values;
        }

        public static BaseTreeNode GetNodeById(BaseTreeNode root, string id)
        {
            if (root.Id == id)
            {
                return root;
            }

            foreach (BaseTreeNode child in root.Children)
            {
                BaseTreeNode foundNode = GetNodeById(child, id);
                if (foundNode != null)
                {
                    return foundNode;
                }
            }

            return null;
        }

        public PageResult<TagConfig> GetTagInfo(TagQueryInputDto input)
        {
            //TODO:获取TagMetaData
            //var TagMetaData = _list.Where(a => a.GroupID == groupId).ToList();

            var device = _project.Objects[input.DriverKey] as DriverConfig;
            if (device == null) return null;
            var group = _project.Objects[input.GroupKey] as GroupConfig;
            var tagConfig = group.TagGroups.Values;
            if (device != null && group != null)
            {
                tagConfig = !string.IsNullOrEmpty(input.SearchValue)
                    ? tagConfig
                    .Where(a => a.Name.Contains(input.SearchValue) || a.Address.Contains(input.SearchValue) || a.Description.Contains(input.SearchValue))
                    .ToList() : tagConfig;
                PageResult<TagConfig> res = new PageResult<TagConfig>()
                {
                    PageNo = input.PageNO,
                    PageSize = input.PageSize,
                    TotalPage = input.TotalPage,
                    TotalRows = input.TotalRows,
                    Rows = tagConfig,
                };
                return DataPaging.SplitList(res);
            }
            return null;
        }

        internal bool SaveTemplateandUpdate(string driverName, out string msg)
        {
            msg = string.Empty;
            var deviceTemplate = _project.Objects[driverName] as DriverConfig;
            if (deviceTemplate == null)
            {
                msg = "更新失败！未找到模板！";
                return false;
            }
            var devices = DConfig.DriverGroups.Values.Where(d => d.TemplateId == deviceTemplate.TemplateId && d.TemplateSync).ToList();
            if (!devices.Any())
            {
                msg = "没有需要更新的设备！";
                return true;
            }
            foreach (var device in devices)
            {
                var newdevice = deviceTemplate.DeepCopy<DriverConfig>();
                foreach (var pair in device.Argument)
                {
                    if (newdevice.Argument.ContainsKey(pair.Key) && !newdevice.Argument[pair.Key].ValueSync)
                        newdevice.Argument[pair.Key].Value = pair.Value.Value;
                }
                newdevice.TemplateSync = true;
                newdevice.NodeKey = device.NodeKey;
                newdevice.Name = device.Name;
                newdevice.DriverNO = device.DriverNO;
                DConfig.DriverGroups.Remove(device);
                DConfig.DriverGroups.Add(newdevice);
            }
            msg = $"更新成功！设备改动 {devices.Count} 台！";
            return true;
        }
    }
}